using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using Xivo.Shared;

namespace Xivo {
  public partial class ScheduleControl : UserControl {
    // drawing variables
    int HighlightedItem = -1;
    ScheduleItem currentItem;
    public ScheduleItem CurrentItem {
      get { return currentItem; }
      set {
        currentItem = value;
        Refresh();
      }
    }
    EditScheduleItemForm EditForm = new EditScheduleItemForm();

    Brush bBlack = System.Drawing.Brushes.Black;
    Brush bWhite = System.Drawing.Brushes.White;
    Brush bGray = System.Drawing.Brushes.DarkGray;
    Brush bSelected = System.Drawing.Brushes.DarkBlue;
    Font font = new Font("Arial", 9);
    int[] cols = new int[] { 120, 30, 30, 120 };
    public string RecordPath {
      get { return Recorder1.RecordPath; }
      set {
        Recorder1.RecordPath = value;
      }
    }

    //public string RecordSource {
    //  get { return recorder1.RecordSource; }
    //  set { recorder1.RecordSource = value; }
    //}

    // the schedule itself
    public List<ScheduleItem> schedule = new List<ScheduleItem>();
    public ScheduleControl() {
      InitializeComponent();
      //if (DesignMode == false)
      //  timer_Tick();
    }

    private void ScheduleControl_Load(object sender, EventArgs e) {
      setScrollMax();
      if (!DesignMode) {
        EditForm.ItemSaved += new EditScheduleItemForm.ItemSavedEvent(EditForm_ItemSaved);
        Common.Radio.onChannelChange += new Delegates.IntEvent(Radio_onChannelChange);
      }
    }

    void Radio_onChannelChange(int value) {
      if (Recorder1.Recording
          && CurrentItem != null
          && value != CurrentItem.Channel)
        Shared.Common.Radio.CurrentChannel = currentItem.Channel;
    }

    void EditForm_ItemSaved(object sender, ScheduleItem e) {
      if (!schedule.Contains(e))
        schedule.Add(e);
      Refresh();
      timer_Tick();
    }

    // never let the timer go too long without a refresh - just in case
    const int timerMax = 30000;
    void SetTimer(DateTime nextEvent) {
      TimeSpan span = nextEvent - DateTime.Now;
      int duration;
      if (span.TotalMilliseconds <= timerMax)
        duration = (int)span.TotalMilliseconds;
      else
        duration = timerMax;
      Console.WriteLine("Duration: " + duration.ToString());
      if (duration <= 0)
        duration = 1;
      timer1.Interval = duration;
      timer1.Enabled = true;
    }

    void setScrollMax() {
      int max = schedule.Count;
      if (vScrollBar1.Value > max)
        vScrollBar1.Value = max;
      vScrollBar1.Maximum = max;
    }

    // fire off the next event (if it's time), then set the next scheduled event on the schedule.
    // set timer to duration of this event so we can stop recording on time.
    public bool Recording {
      get { return Recorder1.Recording; }
    }

    public void StartTimer() {
      timer1.Interval = 5000;
      timer1.Enabled = true;
    }

    private void timer1_Tick(object sender, EventArgs e) {
      if (InvokeRequired)
        Console.WriteLine("Ah HA! Wrong thread!");
      else
        timer_Tick();
    }

    public void timer_Tick() {
      if (Recording) {
        if (currentItem != null && currentItem.isCurrent() == true) {
          if (Shared.Common.Radio.CurrentChannel != currentItem.Channel)
            Shared.Common.Radio.CurrentChannel = currentItem.Channel;
        }

        if (currentItem == null || currentItem.isCurrent() == false) {
          if (currentItem != null)
            currentItem.Advance();
          Recorder1.Stop();
          schedule.Sort();
          CurrentItem = null;
        }
        else
          SetTimer(currentItem.EndTime);
      }

      ScheduleItem item = getNextItem();
      if (!Recorder1.Recording && item != null) {
        if (item.isCurrent()) {
          CurrentItem = item;
          Shared.Common.Radio.CurrentChannel = item.Channel;
          if (Shared.Common.Radio.MuteState == 1)
            Shared.Common.Radio.MuteState = 0;

          Xivo.Shared.ChannelInfo info = new Xivo.Shared.ChannelInfo();
          info.shortTitle = currentItem.Name;
          info.longTitle = CurrentItem.Name;
          info.shortArtist = "";
          info.longArtist = "";
          Recorder1.Start(info, false);
          SetTimer(item.EndTime);
        }
        else
          SetTimer(item.RecordStartTime());
      }

      pbSchedule.Refresh();
    }

    //
    // gets the first active item on the schedule. 
    // an item is no longer active if its sceduled time has passed and there is no repeat time.
    // 
    public ScheduleItem getNextItem() {
      DateTime t = DateTime.MaxValue;
      ScheduleItem ret = null;
      int i = 0;
      while (i < schedule.Count) {
        ScheduleItem item = schedule[i];
        if (item.isCurrent()
          || item.isActive()
          && item.StartTime < t) {
          ret = schedule[i];
          t = item.StartTime;
        }
        ++i;
      }
      return ret;
    }

    private void bAdd_Click(object sender, EventArgs e) {
      EditForm.Item = new ScheduleItem(Shared.Common.Radio.CurrentChannel);
      EditForm.Show();
      EditForm.Activate();
    }

    private void pbSchedule_Paint(object sender, PaintEventArgs e) {
      Graphics g = e.Graphics;
      int i = Shared.Common.bounds(0, schedule.Count - 1, vScrollBar1.Value);
      int y = 0;
      int x = 0;
      int col = 0;
      ScheduleItem item = null;

      g.DrawString("Time", font, bBlack, x, y);
      x += cols[col++];
      g.DrawString("Len", font, bBlack, x, y);
      x += cols[col++];
      g.DrawString("Ch", font, bBlack, x, y);
      x += cols[col++];
      g.DrawString("Name", font, bBlack, x, y);

      x = 0; col = 0;
      y += FontHeight + 2;
      for (int c = 0; c < cols.Length; ++c) {
        x += cols[col++];
        g.FillRectangle(bGray, x, y, 1, pbSchedule.Height);
      }
      g.FillRectangle(bBlack, 0, y, pbSchedule.Width, 1);

      y += 2;
      while (y < pbSchedule.Height && schedule.Count > 0 && i < schedule.Count) {
        item = schedule[i];

        Brush b = bBlack;
        if (i == HighlightedItem) {
          g.FillRectangle(bGray, 0, y, this.Width, font.Height);
          if (!item.Enabled) b = bWhite;
        }
        else if (item == currentItem) {
          g.FillRectangle(bSelected, 0, y, this.Width, font.Height);
          b = bWhite;
        }
        else if (!item.Enabled)
          b = bGray;

        x = 0; col = 0;
        g.DrawString(item.StartTime.ToString("MM-dd, hh:mm:ss t"), font, b, x, y);
        x += cols[col++];
        g.DrawString(item.Duration.ToString(), font, b, x, y);
        x += cols[col++];
        g.DrawString(item.Channel.ToString(), font, b, x, y);
        x += cols[col++];
        g.DrawString(item.Name, font, b, x, y);
        x += cols[col++];
        y += font.Height;
        ++i;
      }
    }

    public void SaveSchedule(string filename) {
      System.IO.StreamWriter outf = new System.IO.StreamWriter(filename);

      foreach (ScheduleItem item in schedule) {
        outf.Write(item.Channel.ToString() + '\t');
        outf.Write(item.DaysOfWeek[0].ToString() + '\t');
        outf.Write(item.DaysOfWeek[1].ToString() + '\t');
        outf.Write(item.DaysOfWeek[2].ToString() + '\t');
        outf.Write(item.DaysOfWeek[3].ToString() + '\t');
        outf.Write(item.DaysOfWeek[4].ToString() + '\t');
        outf.Write(item.DaysOfWeek[5].ToString() + '\t');
        outf.Write(item.DaysOfWeek[6].ToString() + '\t');
        outf.Write(item.Duration.ToString() + '\t');
        outf.Write(item.Enabled.ToString() + '\t'); ;
        outf.Write(item.Name.ToString() + '\t'); ;
        outf.Write(item.RepeatType.ToString() + '\t'); ;
        outf.Write(item.StartTime.ToString() + '\t'); ;
        outf.WriteLine();
      }
      outf.Close();
    }

    public void LoadSchedule(string filename) {
      if (System.IO.File.Exists(filename)) {
        System.IO.StreamReader inf = new System.IO.StreamReader(filename);
        string buffer = inf.ReadLine();
        string[] parts;

        while (buffer != null) {
          parts = buffer.Split('\t');
          ScheduleItem item = new ScheduleItem();
          item.Channel = int.Parse(parts[0]);
          item.DaysOfWeek[0] = bool.Parse(parts[1]);
          item.DaysOfWeek[1] = bool.Parse(parts[2]);
          item.DaysOfWeek[2] = bool.Parse(parts[3]);
          item.DaysOfWeek[3] = bool.Parse(parts[4]);
          item.DaysOfWeek[4] = bool.Parse(parts[5]);
          item.DaysOfWeek[5] = bool.Parse(parts[6]);
          item.DaysOfWeek[6] = bool.Parse(parts[7]);
          item.Duration = int.Parse(parts[8]);
          item.Enabled = bool.Parse(parts[9]);
          item.Name = parts[10];
          item.RepeatType = (ScheduleItem.RepeatTypeEnum)System.Enum.Parse(typeof(ScheduleItem.RepeatTypeEnum), parts[11]);
          item.StartTime = DateTime.Parse(parts[12]);
          item.Advance();
          schedule.Add(item);

          buffer = inf.ReadLine();
        }
        inf.Close();
        schedule.Sort();
      }
    }

    private void pbSchedule_MouseMove(object sender, MouseEventArgs e) {
      int selected = (e.Y / font.Height + vScrollBar1.Value - 1);
      if (selected < schedule.Count) {
        HighlightedItem = selected;
        pbSchedule.Refresh();
      }

    }

    private void pbSchedule_MouseClick(object sender, MouseEventArgs e) {
      if (e.Button == MouseButtons.Left) {
        if (HighlightedItem < schedule.Count && HighlightedItem >= 0) {
          EditForm.Item = schedule[HighlightedItem];
          EditForm.Show();
          EditForm.Activate();
        }
      }
      else if (e.Button == MouseButtons.Right) {
        if (HighlightedItem >= 0 && HighlightedItem < schedule.Count) {
          ScheduleItem item = schedule[HighlightedItem];
          if (MessageBox.Show(null, "Delete item '" + item.Name + "'?", "Delete item", MessageBoxButtons.YesNo) == DialogResult.Yes) {
            if (item == currentItem)
              currentItem = null;
            schedule.Remove(item);
            timer_Tick();
          }
        }
      }
      pbSchedule.Refresh();
    }

    private void pbSchedule_MouseLeave(object sender, EventArgs e) {
      HighlightedItem = -1;
      pbSchedule.Refresh();
    }
  }

}
